/**
 * 安装指令
 * @param Vue vue实例
 */
import Vue from 'vue'

export default function directive(Vue) {
	// 懒加载el-select
	Vue.directive('el-select-loadmore', {
		bind: (el, binding) => {
			const SELECTWRAP_DOM = el.querySelector(
			  '.el-select-dropdown .el-select-dropdown__wrap'
			);
			SELECTWRAP_DOM.addEventListener('scroll', function() {
			  const condition =
			    this.scrollHeight - this.scrollTop <= this.clientHeight;
			  if (condition) {
			    binding.value();
			  }
			});
		}
	});
	// dialog 拖动
	Vue.directive('dialogDrag', {
	  bind: (el) => {
	    // 获取弹框标题区域DOM节点
	    const headerDOM = el.querySelector('.el-dialog__header');
	    // 修改鼠标图标样式
	    headerDOM.style.cursor = "move";
	    // 禁止拖拽时选中标题中文本内容
	    headerDOM.style.userSelect = "none";
	    // 获取弹框区域的DOM节点
	    const dialogDOM = el.querySelector('.el-dialog');
	    let isDown = false,         // 是否按下
	        // 鼠标按下时坐标位置
	        clientX = 0,
	        clientY = 0,
	        // 按下时弹框位置
	        dialogLeft = 0,
	        dialogTop = 0;
	    // 定义函数判断当前是否在可见范围内
	    function boundingRange(){
	      const bounding = dialogDOM.getBoundingClientRect();
	      return {
	        top: bounding.top >= 0,       // 表示顶部在可见范围
	        left: bounding.left >= 0,     // 表示左侧在可见范围
	        right: bounding.left < window.innerWidth - bounding.width,   // 表示右侧在指定范围
	        bottom: bounding.top < window.innerHeight - bounding.height   // 表示底部在指定范围
	      }
	    }
		// 更新数据
	    function update(e){
	      // 获取当前鼠标按钮位置坐标
	      clientX = e.clientX;
	      clientY = e.clientY;
	      // 获取弹框位置（默认情况弹框样式left和top可能不存在，当为NaN时初始化为0）
	      dialogLeft = isNaN(parseFloat(dialogDOM.style.left))?0:parseFloat(dialogDOM.style.left);
	      dialogTop = isNaN(parseFloat(dialogDOM.style.top))?0:parseFloat(dialogDOM.style.top);
	    }
	    // 监听鼠标按下事件
	    headerDOM.onmousedown = e => {
	      isDown = true;
	      update(e);
	    }
	    // 监听鼠标移动事件
	    headerDOM.onmousemove = e => {
	      // 不按下的时候，执行移动操作
	      if(isDown){
	        // 获取DOM边界范围
	        const range = boundingRange();
	        // 获取当前移动到的位置坐标,与按下位置坐标进行计算，获取移动距离
	        const distX = e.clientX - clientX;          // distX小于0为向左，大于0为向右
	        const distY = e.clientY - clientY;          // distY小于0为向上，大于0为向下
	        // 判断左侧或右侧是否可移动
	        if((range.left && distX < 0) || (range.right && distX >= 0)) dialogDOM.style.left = (dialogLeft + distX) + "px";
	        // 判断顶部或者底部是否可移动
	        if((range.top && distY < 0) || (range.bottom && distY >= 0)) dialogDOM.style.top = (dialogTop + distY) + "px";
			// 更新起始位数据
			update(e);
	      }
	    }
	    headerDOM.onmouseup = e => isDown = false;
	    window.onmouseup = () => isDown = false;
	  }
	});
    // 粗体指令
	Vue.directive('bold', {
    inserted(el) {
      el.style.fontWeight = 'bold'
    }
	});

  // 自生成编码
	Vue.directive('autoCode', {
	  inserted: function (el, binding) {
		// 生成编码的逻辑
		function generateCode() {
		  const now = new Date(); //创建时间日期对象
		  const year = now.getFullYear(); //年
		  const month = now.getMonth() + 1; //月份是从0开始的
		  const day = now.getDate(); //日
		  const hours = now.getHours(); //小时
		  const minutes = now.getMinutes(); //分钟
		  const seconds = now.getSeconds(); //秒
		  let timestamp = `${year}${month}${day}` + `${hours}${minutes}${seconds}`
		  return `${timestamp}`;
		}
	 
		// 设置el-input的值
		let deptCode = el.querySelector('input').value = binding.value || generateCode();
		// 1、生成成功以后，把value存入到SessionStorage中
		sessionStorage.setItem('deptCode', JSON.stringify(deptCode))
	  }
	});
  // 节流函数
  Vue.directive('throttle', {
    inserted: function(el, binding) {
      let timeoutId
      let lastExecutedTime = 0
      const { value, arg, modifiers } = binding
      const delay = modifiers.immediate ? +arg || 200 : +arg || 0
      const execute = function() {
        clearTimeout(timeoutId)
        value();
        lastExecutedTime = Date.now()
      }
      el.addEventListener('click', function() {
        const currentTime = Date.now()
        if (currentTime - lastExecutedTime >= delay) {
          execute()
        } else {
          clearTimeout(timeoutId)
          timeoutId = setTimeout(execute, delay)
        }
      })
    }
  })
	// 外部点击
	Vue.directive('out-click', {
	    bind: function(el, binding, vnode) {
	      el.clickOutsideEvent = function(event) {
	        if (!(el === event.target || el.contains(event.target))) {
	          binding.value.call(this, event);
	        }
	      };
	      document.body.addEventListener('click', el.clickOutsideEvent);
	    },
	    unbind: function(el) {
	      document.body.removeEventListener('click', el.clickOutsideEvent);
	    },
	});
	// 自动聚焦
	Vue.directive('focus', {
	inserted: function(el) {
	    el.focus();
	},
	});
	// 图片懒加载
	Vue.directive('lazy-img', {
	    inserted: function(el, binding) {
	      const img = new Image();
	      img.src = binding.value;
	  
	      img.onload = () => {
	        el.src = binding.value;
	      };
	    },
	  });
	// 防止重复点击
	Vue.directive('noMoreClick', {
	    inserted(el, binding) {
	      el.addEventListener('click', () => {
	        el.style.pointerEvents = 'none'
	        setTimeout(() => {
	          el.style.pointerEvents = ''
	        }, 1000)
	      })
	    }
	  })
	// 复制到粘贴板
	Vue.directive('clipboard', {
	    bind(el, binding) {
	      if (binding.arg === 'success') {
	        el._v_clipboard_success = binding.value
	      } else if (binding.arg === 'error') {
	        el._v_clipboard_error = binding.value
	      } else {
	        const clipboard = new Clipboard(el, {
	          text() { return binding.value },
	          action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
	        })
	        clipboard.on('success', e => {
	          const callback = el._v_clipboard_success
	          callback && callback(e)
	        })
	        clipboard.on('error', e => {
	          const callback = el._v_clipboard_error
	          callback && callback(e)
	        })
	        el._v_clipboard = clipboard
	      }
	    },
	    unbind(el, binding) {
	      if (binding.arg === 'success') {
	        delete el._v_clipboard_success
	      } else if (binding.arg === 'error') {
	        delete el._v_clipboard_error
	      } else {
	        el._v_clipboard.destroy()
	        delete el._v_clipboard
	      }
	    }
	  })
	// 滚动加载
	Vue.directive('scroll-load', {
	    inserted(el, binding) {
	      const loadFunction = binding.value;
	      const scrollWrapper = el;
	  
	      scrollWrapper.addEventListener('scroll', function () {
	        const scrollTop = scrollWrapper.scrollTop;
	        const scrollHeight = scrollWrapper.scrollHeight;
	        const clientHeight = scrollWrapper.clientHeight;
	  
	        if (scrollTop + clientHeight >= scrollHeight * 0.95) {
	          loadFunction();
	        }
	      });
	    }
	  });
	// 动态元素高度
	Vue.directive('auto-height', {
	    componentUpdated(el, binding) {
	      const resize = () => {
	        el.style.height = 'auto';
	        el.style.height = el.scrollHeight + 'px';
	      };
	  
	      el.addEventListener('input', resize);
	      resize(); // 初始化时调整一次
	    }
	  });
	// 自定义长按事件：
	Vue.directive('long-press', {
	    bind(el, binding) {
	      const pressTime = binding.arg;
	      const pressHandler = binding.value;
	  
	      let pressTimer = null;
	  
	      const startHandler = () => {
	        clearTimeout(pressTimer);
	        pressTimer = setTimeout(() => {
	          pressHandler();
	        }, pressTime);
	      };
	  
	      const stopHandler = () => {
	        clearTimeout(pressTimer);
	      };
	  
	      el.addEventListener('mousedown', startHandler);
	      el.addEventListener('mouseup', stopHandler);
	      el.addEventListener('mouseleave', stopHandler);
	    },
	    unbind(el) {
	      el.removeEventListener('mousedown', startHandler);
	      el.removeEventListener('mouseup', stopHandler);
	      el.removeEventListener('mouseleave', stopHandler);
	    }
	  });
	  // 限制输入框智能输入数字
	  Vue.directive('number-only', {
	    bind(el) {
	      function handleInput(event) {
	        // 处理输入事件
	        // 获取输入框的值
	        const inputValue = event.target.value;
	        // 将非数字字符替换为空字符串，得到格式化后的值
	        const formattedValue = inputValue.replace(/[^\d]/g, '');
	         // 如果原始值和格式化后的值不相等
	         // 将输入框的值设置为格式化后的值
	        if (inputValue !== formattedValue) {
	          event.target.value = formattedValue;
	          // 阻止默认行为
	          event.preventDefault();
	        }
	      }
	  
	      el.addEventListener('input', handleInput);
	      el.$_number_only_destroy = () => {
	        el.removeEventListener('input', handleInput);
	      };
	    },
	    unbind(el) {
	      el.$_number_only_destroy();
	    }
	  });
	  // 触摸滑动处理
	  Vue.directive('touch-swipe', {
	    bind(el, binding) {
	      let startX, startY, startTime;
	      const handler = binding.value;
	      const touchEvent = e => {
	        const touch = e.touches[0];
	        switch (e.type) {
	          case 'touchstart':
	            startX = touch.clientX;
	            startY = touch.clientY;
	            startTime = new Date().getTime();
	            break;
	          case 'touchend':
	            const deltaX = touch.clientX - startX;
	            const deltaY = touch.clientY - startY;
	            const totalTime = new Date().getTime() - startTime;
	  
	            if (Math.abs(deltaX) > 30 && totalTime < 1000) {
	              handler(deltaX > 0 ? 'right' : 'left');
	            }
	  
	            if (Math.abs(deltaY) > 30 && totalTime < 1000) {
	              handler(deltaY > 0 ? 'down' : 'up');
	            }
	            break;
	        }
	      };
	  
	      el.addEventListener('touchstart', touchEvent);
	      el.addEventListener('touchend', touchEvent);
	      el.$_touch_swipe_destroy = () => {
	        el.removeEventListener('touchstart', touchEvent);
	        el.removeEventListener('touchend', touchEvent);
	      };
	    },
	    unbind(el) {
	      el.$_touch_swipe_destroy();
	    }
	  });
	  // 元素拖拽
	  Vue.directive('draggable', {
	    bind(el) {
	      let startX, startY, initialX, initialY;
	      let isDragging = false;
	  
	      function handleMouseDown(event) {
	        startX = event.clientX;
	        startY = event.clientY;
	        initialX = parseFloat(el.style.left) || 0;
	        initialY = parseFloat(el.style.top) || 0;
	        isDragging = true;
	      }
	  
	      function handleMouseMove(event) {
	         // 处理鼠标移动事件
	        // 如果不处于拖拽状态，则直接返回
	        if (!isDragging) return;
	        // 计算鼠标移动的差值
	        const deltaX = event.clientX - startX;
	        const deltaY = event.clientY - startY;
	        // 根据差值计算新的位置
	        const newX = initialX + deltaX;
	        const newY = initialY + deltaY;
	        // 设置元素的新位置
	        el.style.left = newX + 'px';
	        el.style.top = newY + 'px';
	      }
	  
	      function handleMouseUp() {
	        isDragging = false;
	      }
	  
	      el.addEventListener('mousedown', handleMouseDown);
	      document.addEventListener('mousemove', handleMouseMove);
	      document.addEventListener('mouseup', handleMouseUp);
	      el.$_draggable_destroy = () => {
	        el.removeEventListener('mousedown', handleMouseDown);
	        document.removeEventListener('mousemove', handleMouseMove);
	        document.removeEventListener('mouseup', handleMouseUp);
	      };
	    },
	    unbind(el) {
	      el.$_draggable_destroy();
	    }
	  });
	  // 自定义点击外部元素关闭模态的指令
	  Vue.directive('click-outside', {
	    bind: function (el, binding, vnode) {
	      el.clickOutsideEvent = function (event) {
	        if (!(el === event.target || el.contains(event.target))) {
	          vnode.context[binding.expression](event);
	        }
	      };
	      document.body.addEventListener('click', el.clickOutsideEvent);
	    },
	    unbind: function (el) {
	      document.body.removeEventListener('click', el.clickOutsideEvent);
	    }
	  });
	  // 图片懒加载
	  Vue.directive('lazy', {
	    bind(el, binding) {
	      const img = new Image();
	      const color = Math.floor(Math.random() * 1000000);
	      img.src = binding.value;
	      el.style.backgroundColor = '#' + color;
	      img.onload = function () {
	        el.style.backgroundImage = 'url(' + binding.value + ')';
	      }
	    }
	  });
	  // 鼠标悬停变色
	  Vue.directive('hovercolor', {
	    bind(el, binding, vnode) {
	      el.onmouseover = function() {
	        el.style.color = binding.value; // 使用绑定的值作为颜色
	      }
	      el.onmouseout = function() {
	        el.style.color = ''; // 鼠标移出后颜色恢复
	      }
	    }
	  });
	  // 文字提示
	  Vue.directive('tooltip', {
	    bind(el, binding, vnode) {
	      var tooltip = document.createElement('div');
	      tooltip.style.position = 'absolute';
	      tooltip.style.bottom = '100%';
	      tooltip.style.left = '0';
	      tooltip.style.padding = '5px 10px';
	      tooltip.style.backgroundColor = '#333';
	      tooltip.style.color = '#fff';
	      tooltip.style.borderRadius = '5px';
	      tooltip.style.marginBottom = '10px';
	      tooltip.style.opacity = '0';
	      tooltip.style.transition = '0.3s';
	      tooltip.innerHTML = binding.value;
	  
	      el.onmouseover = function() {
	        tooltip.style.opacity = '1';
	      }
	      el.onmouseout = function() {
	        tooltip.style.opacity = '0';
	      }
	  
	      el.appendChild(tooltip);
	    }
	  });
	  // 图片预先加载
	  Vue.directive('img-preload', {
	    bind(el, binding, vnode) {
	      var img = new Image();
	       // 首先设置占位图
	      el.src = 'path/to/placeholder.jpg';
	      img.onload = function() {
	        // 实际图片加载完成后替换
	        el.src = binding.value; 
	      }
	      // 开始加载实际图片
	      img.src = binding.value; 
	    }
	  })
}
